/** *************************************************************************
 *  @file       8021AS_PTP.c
 *  @brief	    802.1AS OSS同步函数
 *  @date		2022/11/21
 *  @author		yalan.liu
 *  @version	1.0.0
 ****************************************************************************/

#include "../include/8021AS_PTP.h"
#include "../include/ptp_tsninsight.h"
#include <math.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>

#define LOG_SIZE 100 * 1024 * 1024 // 100MB
#define SYNC_LOG_FILE "oss_sync_log.txt"
#define DELAY_LOG_FILE "oss_delay_log.txt"
#define OFFSET_LOG_FILE "oss_offset_log.txt"

u8 fre_switch = 0; // 频率校正开关
u8 step_mode = 0;	 // 0代表两步模式，1代表1步模式

int sync_flie_count = 0;
int delay_flie_count = 0;
int offset_flie_count = 0;
u64 g_timer_array[2] = {0};

int sync_logger(const char *file, const char *function, int line, const char *fmt, ...)
{
	FILE *logger = NULL;
	va_list ap;

	struct stat stat_buf;
	char cmd[128] = {0};
	char str[] = "****** sync message ******\n";

	va_start(ap, fmt);

	if (stat(SYNC_LOG_FILE, &stat_buf) < 0)
	{
		write_debug_msg("sync_log_file_path = %s,stat eeror!\n", SYNC_LOG_FILE);
	}

	if (stat_buf.st_size > LOG_SIZE)
	{
		sync_flie_count++;
		sprintf(cmd, "mv oss_sync_log.txt oss_sync_log_%d.txt", sync_flie_count);
		system(cmd);

		logger = fopen(SYNC_LOG_FILE, "w");

		fwrite(str, sizeof(char), strlen(str), logger);
	}
	else
	{
		logger = fopen(SYNC_LOG_FILE, "a+");
	}

	// fprintf(logger, "%s[%d]: ",function, line);
	vfprintf(logger, fmt, ap);
	// fprintf(logger, "\n");

	fflush(logger);
	// end to parse variable arguments
	va_end(ap);
	fclose(logger);
	return 0;
}

int delay_logger(const char *file, const char *function, int line, const char *fmt, ...)
{
	FILE *logger = NULL;
	va_list ap;

	struct stat stat_buf;
	char cmd[128] = {0};
	char str[] = "****** delay message ******\n";

	va_start(ap, fmt);

	if (stat(DELAY_LOG_FILE, &stat_buf) < 0)
	{
		write_debug_msg("delay_log_file_path = %s,stat eeror!\n", DELAY_LOG_FILE);
	}

	if (stat_buf.st_size > LOG_SIZE)
	{
		delay_flie_count++;
		sprintf(cmd, "mv oss_delay_log.txt oss_delay_log_%d.txt", delay_flie_count);
		system(cmd);

		logger = fopen(DELAY_LOG_FILE, "w");

		fwrite(str, sizeof(char), strlen(str), logger);
	}
	else
	{
		logger = fopen(DELAY_LOG_FILE, "a+");
	}

	vfprintf(logger, fmt, ap);

	fflush(logger);
	va_end(ap);
	fclose(logger);
	return 0;
}

int offset_logger(const char *file, const char *function, int line, const char *fmt, ...)
{
	FILE *logger = NULL;
	va_list ap;

	struct stat stat_buf;
	char cmd[128] = {0};
	char str[] = "****** offset message ******\n";

	va_start(ap, fmt);

	if (stat(OFFSET_LOG_FILE, &stat_buf) < 0)
	{
		write_debug_msg("offset_log_file_path = %s,stat eeror!\n", OFFSET_LOG_FILE);
	}

	if (stat_buf.st_size > LOG_SIZE)
	{
		offset_flie_count;
		sprintf(cmd, "mv oss_offset_log.txt oss_offset_log_%d.txt", offset_flie_count);
		system(cmd);

		logger = fopen(OFFSET_LOG_FILE, "w");

		fwrite(str, sizeof(char), strlen(str), logger);
	}
	else
	{
		logger = fopen(OFFSET_LOG_FILE, "a+");
	}

	// fprintf(logger, "%s[%d]: ",function, line);
	vfprintf(logger, fmt, ap);
	// fprintf(logger, "\n");

	fflush(logger);
	// end to parse variable arguments
	va_end(ap);
	fclose(logger);
	return 0;
}

int os_pkt_receive_send_init(u8 *net_interface, u8 *filter_rule)
{
	struct sock_fprog filter;
	int re;

	struct sock_filter code[] = {
			{0x28, 0, 0, 0x00000000},
			{0x15, 0, 6, 0x00006626},
			{0x30, 0, 0, 0x00000002},
			{0x15, 0, 4, 0x00000062},
			{0x30, 0, 0, 0x00000005},
			{0x15, 0, 2, 0x00000002},
			{0x28, 0, 0, 0x0000000c},
			{0x15, 6, 0, 0x0000ff01},
			{0x28, 0, 0, 0x0000000c},
			{0x15, 0, 5, 0x00000800},
			{0x30, 0, 0, 0x00000017},
			{0x15, 0, 3, 0x00000011},
			{0x28, 0, 0, 0x00000024},
			{0x15, 0, 1, 0x00002381},
			{0x06, 0, 0, 0x0000ffff},
			{0x06, 0, 0, 0x00000000},
	};

	filter.len = 16;
	filter.filter = code;
	re = tsmp_pkt_send_recv_init(net_interface, filter);
	return re;
}

void get_opensync_mac_from_mid(u8 *mac, u16 mid)
{
	mac[0] = 0x66;
	mac[1] = 0x26;
	mac[2] = 0x62;
	mac[3] = (mid >> 4) & 0xff;
	mac[4] = (mid & 0xf) << 4;
	mac[5] = 0x02;
}

void riprt_n(char *str)
{
	int len, i;

	if (str == NULL)
		return;
	len = strlen(str);
	if (len == 0)
		return;

	for (i = 0; i < len; i++)
	{
		if (str[i] == '\r' || str[i] == '\n')
			str[i] = '\t';
	}
}

int parse_node_object_sync_info(cJSON *node_json, sync_context *sync_para_context)
{
	u32 tvalue32 = 0;
	u16 tvalue16 = 0;
	u8 tvalue8 = 0;

	u16 hcp_mid = 0;

	cJSON *tmp_json = NULL;

	// 获取节点同步参数信息
	tmp_json = cJSON_GetObjectItem(node_json, "hcp_mid");

	if (NULL == tmp_json)
	{
		printf("can not find  hcp_mid object!\n");
		return -1;
	}
	else
	{
		sscanf(tmp_json->valuestring, "%hx", &tvalue16);
		hcp_mid = tvalue16;

		sync_para_context->context_info.node_context[hcp_mid] = (node_info *)malloc(sizeof(node_info));
		bzero(sync_para_context->context_info.node_context[hcp_mid], sizeof(node_info));
		sync_para_context->context_info.node_context[hcp_mid]->cfg_para.mid = hcp_mid;

		if (hcp_mid == sync_para_context->context_info.gm_mid)
		{
			sync_para_context->context_info.node_context[hcp_mid]->cfg_para.gm_flag = 1;
		}
		else
		{
			sync_para_context->context_info.node_context[hcp_mid]->cfg_para.gm_flag = 0;
		}
		printf("hcp_mid 0x%hx \n", hcp_mid);
	}

	tmp_json = cJSON_GetObjectItem(node_json, "master_port");
	if (NULL == tmp_json)
	{
		printf("can not find  master_port object!\n");
		return -1;
	}
	else
	{
		sscanf(tmp_json->valuestring, "%x", &tvalue32);
		sync_para_context->context_info.node_context[hcp_mid]->cfg_para.master_port = tvalue32;
		printf("node_context[%d]->cfg_para.master_port = 0x%x \n", hcp_mid, tvalue32);
	}

	tmp_json = cJSON_GetObjectItem(node_json, "slave_port");
	if (NULL == tmp_json)
	{
		printf("can not find  slave_port object!\n");
		return -1;
	}
	else
	{
		sscanf(tmp_json->valuestring, "%x", &tvalue32);
		sync_para_context->context_info.node_context[hcp_mid]->cfg_para.slave_port = tvalue32;
		printf("node_context[%d]->cfg_para.slave_port = 0x%x \n", hcp_mid, tvalue32);
	}

	tmp_json = cJSON_GetObjectItem(node_json, "port_ptp_enabled");
	if (NULL == tmp_json)
	{
		printf("can not find  port_ptp_enabled object!\n");
		return -1;
	}
	else
	{
		sscanf(tmp_json->valuestring, "%x", &tvalue32);
		sync_para_context->context_info.node_context[hcp_mid]->cfg_para.port_ptp_enabled = tvalue32;
		printf("node_context[%d]->cfg_para.port_ptp_enabled = 0x%x \n", hcp_mid, tvalue32);
	}

	tmp_json = cJSON_GetObjectItem(node_json, "sync_period");
	if (NULL == tmp_json)
	{
		printf("can not find  sync_period object!\n");
		return -1;
	}
	else
	{
		sscanf(tmp_json->valuestring, "%hhx", &tvalue8);
		sync_para_context->context_info.node_context[hcp_mid]->cfg_para.sync_period = tvalue8;
		printf("node_context[%d]->cfg_para.sync_period = 0x%hhx \n", hcp_mid, tvalue8);
	}

	tmp_json = cJSON_GetObjectItem(node_json, "measure_period");
	if (NULL == tmp_json)
	{
		printf("can not find  measure_period object!\n");
		return -1;
	}
	else
	{
		sscanf(tmp_json->valuestring, "%hhx", &tvalue8);
		sync_para_context->context_info.node_context[hcp_mid]->cfg_para.measure_period = tvalue8;
		printf("node_context[%d]->cfg_para.measure_period = 0x%hhx \n", hcp_mid, tvalue8);
	}

	tmp_json = cJSON_GetObjectItem(node_json, "measure_timeout");
	if (NULL == tmp_json)
	{
		printf("can not find  measure_timeout object!\n");
		return -1;
	}
	else
	{
		sscanf(tmp_json->valuestring, "%hhx", &tvalue8);
		sync_para_context->context_info.node_context[hcp_mid]->cfg_para.measure_timeout = tvalue8;
		printf("node_context[%d]->cfg_para.measure_timeout = 0x%hhx \n", hcp_mid, tvalue8);
	}

	tmp_json = cJSON_GetObjectItem(node_json, "report_enable");
	if (NULL == tmp_json)
	{
		printf("can not find  report_enable object!\n");
		return -1;
	}
	else
	{
		sscanf(tmp_json->valuestring, "%hhx", &tvalue8);
		sync_para_context->context_info.node_context[hcp_mid]->cfg_para.report_enable = tvalue8;
		printf("node_context[%d]->cfg_para.report_enable = 0x%hhx \n", hcp_mid, tvalue8);
	}

	tmp_json = cJSON_GetObjectItem(node_json, "offset_threshold");
	if (NULL == tmp_json)
	{
		printf("can not find  offset_threshold object!\n");
		return -1;
	}
	else
	{
		sscanf(tmp_json->valuestring, "%hx", &tvalue16);
		sync_para_context->context_info.node_context[hcp_mid]->cfg_para.offset_threshold = tvalue16;
		printf("node_context[%d]->cfg_para.offset_threshold = 0x%hx \n", hcp_mid, tvalue16);
	}

	tmp_json = cJSON_GetObjectItem(node_json, "tick_interval_flag");
	if (NULL == tmp_json)
	{
		printf("can not find  tick_interval_flag object!\n");
		return -1;
	}
	else
	{
		sscanf(tmp_json->valuestring, "%hhx", &tvalue8);
		sync_para_context->context_info.node_context[hcp_mid]->cfg_para.tick_interval_flag = tvalue8;
		printf("node_context[%d]->cfg_para.tick_interval_flag = 0x%hhx \n", hcp_mid, tvalue8);
	}

	return 0;
}

int get_sync_node_info(char *buf, sync_context *sync_para_context, u16 *oss_mid)
{
	int ret = 0;
	int array_num = 0;
	int i = 0;
	u16 tvalue16 = 0;
	u8 tvalue8 = 0;
	u16 gm_id = 0;

	cJSON *root_json = NULL;
	cJSON *sync_cfg_para_json = NULL;
	cJSON *oss_json = NULL;
	cJSON *node_json = NULL;
	cJSON *tmp_json = NULL;

	riprt_n(buf);
	root_json = cJSON_Parse(buf);

	if (!root_json)
	{
		printf("parse root_json error, Error before: [%s]\n", cJSON_GetErrorPtr());
		return -1;
	}

	sync_cfg_para_json = cJSON_GetObjectItem(root_json, "sync_cfg_para");
	if (!sync_cfg_para_json)
	{
		printf("parse sync_cfg_para error, Error before: [%s]\n", cJSON_GetErrorPtr());
		cJSON_Delete(root_json);
		return -1;
	}

	oss_json = cJSON_GetObjectItem(sync_cfg_para_json, "oss");
	if (!oss_json)
	{
		printf("parse oss_json error, Error before: [%s]\n", cJSON_GetErrorPtr());
		cJSON_Delete(root_json);
		return -1;
	}
	else
	{
		tmp_json = cJSON_GetObjectItem(oss_json, "oss_mid");
		if (!tmp_json)
		{
			printf("parse oss_mid error, Error before: [%s]\n", cJSON_GetErrorPtr());
			cJSON_Delete(root_json);
			return -1;
		}
		else
		{
			sscanf(tmp_json->valuestring, "%hx", &tvalue16);
			*oss_mid = tvalue16;
			printf("oss_mid = 0x%hx \n", *oss_mid);
		}

		tmp_json = cJSON_GetObjectItem(oss_json, "gm_mid");
		if (!tmp_json)
		{
			printf("parse gm_mid error, Error before: [%s]\n", cJSON_GetErrorPtr());
			cJSON_Delete(root_json);
			return -1;
		}
		else
		{
			sscanf(tmp_json->valuestring, "%hx", &tvalue16);
			sync_para_context->context_info.gm_mid = tvalue16;
			printf("sync_para_context->context_info.gm_mid = 0x%hx \n", sync_para_context->context_info.gm_mid);
		}

		tmp_json = cJSON_GetObjectItem(oss_json, "fre_switch");
		if (!tmp_json)
		{
			printf("parse fre_switch error, Error before: [%s]\n", cJSON_GetErrorPtr());
			cJSON_Delete(root_json);
			return -1;
		}
		else
		{
			sscanf(tmp_json->valuestring, "%hhx", &tvalue8);
			fre_switch = tvalue8;
			printf("fre_switch = 0x%hx \n", tvalue8);
		}

		tmp_json = cJSON_GetObjectItem(oss_json, "one_step_mode");
		if (!tmp_json)
		{
			printf("parse one_step_mode error, Error before: [%s]\n", cJSON_GetErrorPtr());
			cJSON_Delete(root_json);
			return -1;
		}
		else
		{
			sscanf(tmp_json->valuestring, "%hhx", &tvalue8);
			step_mode = tvalue8;
			printf("step_mode = 0x%hhx \n", tvalue8);
		}
	}

	node_json = cJSON_GetObjectItem(sync_cfg_para_json, "node");
	if (!node_json)
	{
		printf("parse node_json error, Error before: [%s]\n", cJSON_GetErrorPtr());
		cJSON_Delete(root_json);
		return -1;
	}

	// 有多个节点情况
	if (node_json->type == cJSON_Array)
	{
		array_num = cJSON_GetArraySize(node_json);
		printf("array_num = %d \n", array_num);

		if (array_num == 0)
		{
			printf("parse_sync_info, node = NULL! \n");
			cJSON_Delete(root_json);
			return -1;
		}

		for (i = 0; i < array_num; i++)
		{
			tmp_json = cJSON_GetArrayItem(node_json, i);

			if (!tmp_json)
			{
				printf("parse sync_node_entry_json error, Error before: [%s]\n", cJSON_GetErrorPtr());
				cJSON_Delete(root_json);
				return -1;
			}

			// 获取单个节点的同步信息
			ret = parse_node_object_sync_info(tmp_json, sync_para_context);
			if (ret == -1)
			{
				printf("parse_node_object_sync_info error!\n");
				cJSON_Delete(root_json);
				return -1;
			}
		}
	}
	else if (node_json->type == cJSON_Object)
	{
		// 获取单个节点的同步信息
		ret = parse_node_object_sync_info(node_json, sync_para_context);
	}

	cJSON_Delete(root_json);

	return ret;
}

int get_sync_cfg_info(u8 *cfg_file_name, sync_context *sync_para_context, u16 *oss_mid)
{
	int ret = 0;

	FILE *fp;
	char *buf;
	fp = fopen(cfg_file_name, "r");

	if (fp == NULL)
	{
		printf("fopen %s error\n", cfg_file_name);
		return -1;
	}

	// 确定文件大小, 并将读取指针移回文件开始
	fseek(fp, 0, SEEK_END);
	long pos = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	if (pos <= 0)
	{
		printf("%s Invalid!\n", cfg_file_name);
		fclose(fp);
		return -1;
	}

	// 根据文件大小申请内存空间, 注意这边要多申请1个字节用于存放'\0'
	buf = (char *)malloc(pos + 1);
	if (buf == NULL)
	{
		printf("No enough memory.");
		fclose(fp);
		return -1;
	}
	bzero(buf, pos + 1);

	// 读取文件内容至buff
	int nread = fread(buf, pos, 1, fp);
	if (!nread)
	{
		printf("Failed to read the config file.");
		free(buf);
		fclose(fp);
		return -1;
	}

	// 解析json，获取各个节点同步信息
	ret = get_sync_node_info(buf, sync_para_context, oss_mid);

	if (buf != NULL)
	{
		free(buf);
	}

	// 关闭文件
	fclose(fp);

	return ret;
}

// 时间同步系统初始化函数
int sync_init(u8 *network_interface)
{
	int ret;

	// 报文发送和接收初始化
	//  sprintf(test_rule,"%s","(ether[0:2]=0x6626 && ether[2]=0x62 && ether[5]=0x2 && ether[12:2]=0xff01) || (ether[12:2]=0x0800 && ether[23]=0x11 && ether[36:2]=0x2381)");
	ret = os_pkt_receive_send_init(network_interface, " ");
	if (ret == -1)
	{
		printf("os_pkt_receive_send_init fail \n");
		return -1;
	}

	return 0;
}

void cfg_corr_fre_value_no_check(u16 hcp_mid, u8 *pkt, u64 reg_data, u32 reg_addr, u32 offset, u32 bit_flag, node_check_info *check_info)
{
	int ret = 0;
	u8 local_mac[6] = {0};
	u8 *data = NULL;
	u16 data_num = 2;
	u8 len = 8;
	u8 check_bit = 0;

	// 读出寄存器对应的bit位
	check_bit = check_info->check_flag & (0x00000001 << bit_flag);
	// 上一个周期内未收到配置响应报文
	if (check_bit)
	{
		printf("check error: No response pkt is received in a synchronization period\n");
		printf("hcp_mid = %d, reg_addr = %d\n", hcp_mid, reg_addr);
		write_debug_msg("check error: No response pkt is received in a synchronization period\n");
		write_debug_msg("hcp_mid = %d, reg_addr = %d\n", hcp_mid, reg_addr);
	}

	bzero(pkt, MAX_PKT_LEN);

	// data内容直接放到pkt中，省去再次赋值
	data = (u8 *)(pkt + sizeof(tsmp_header) + sizeof(tsmp_set_req_or_get_res_pkt_data)); // 配置的数据

	get_hcp_mac_from_mid(local_mac, hcp_mid);

	memcpy(data, (u8 *)&reg_data, len);

	tsmp_set_req(local_mac, data_num, reg_addr, pkt); // 写请求

	// 保存此次配置的数据
	memcpy(((u8 *)&check_info->buf) + offset, pkt + sizeof(tsmp_header), 10);

	// 读寄存器数据
	tsmp_get_req(local_mac, data_num, reg_addr, pkt); // 读请求

	// 将寄存器对应的bit位置1
	check_info->check_flag |= (0x00000001 << bit_flag);

	return;
}

void cfg_reg_value_no_check(u16 hcp_mid, u8 *pkt, u32 reg_data, u32 reg_addr, u32 offset, u32 bit_flag, node_check_info *check_info)
{
	int ret = 0;
	u8 local_mac[6] = {0};
	u8 *data = NULL;
	u16 data_num = 1;
	u8 len = 4;
	u8 check_bit = 0;

	// 读出寄存器对应的bit位
	check_bit = check_info->check_flag & (0x00000001 << bit_flag);
	// 上一个周期内未收到配置响应报文
	if (check_bit)
	{
		// printf("check error: No response pkt is received in a synchronization period\n");
		// printf("hcp_mid = %d, reg_addr = %d\n", hcp_mid, reg_addr);
		write_debug_msg("check error: No response pkt is received in a synchronization period\n");
		write_debug_msg("hcp_mid = %d, reg_addr = %d\n", hcp_mid, reg_addr);
	}

	bzero(pkt, MAX_PKT_LEN);

	// data内容直接放到pkt中，省去再次赋值
	data = (u8 *)(pkt + sizeof(tsmp_header) + sizeof(tsmp_set_req_or_get_res_pkt_data)); // 配置的数据

	get_hcp_mac_from_mid(local_mac, hcp_mid);

	memcpy(data, (u8 *)&reg_data, len);

	tsmp_set_req(local_mac, data_num, reg_addr, pkt); // 写请求

	// 保存此次配置的数据
	memcpy(((u8 *)&check_info->buf) + offset, pkt + sizeof(tsmp_header), 10);

	// 读寄存器数据
	tsmp_get_req(local_mac, data_num, reg_addr, pkt); // 读请求

	// 将寄存器对应的bit位置1
	check_info->check_flag |= (0x00000001 << bit_flag);

	return;
}

int cfg_reg_value(u16 hcp_mid, u8 *pkt, u32 reg_data, u32 reg_addr)
{
	int ret = 0;
	u8 local_mac[6] = {0};
	u8 *data = NULL;
	u16 data_num = 1;
	u8 len = 4;

	bzero(pkt, MAX_PKT_LEN);

	// data内容直接放到pkt中，省去再次赋值
	data = (u8 *)(pkt + sizeof(tsmp_header) + sizeof(tsmp_set_req_or_get_res_pkt_data)); // 配置的数据

	get_hcp_mac_from_mid(local_mac, hcp_mid);

	memcpy(data, (u8 *)&reg_data, len);

	tsmp_set_req(local_mac, data_num, reg_addr, pkt); // 写请求

	// 配置验证
	ret = cfg_varify(local_mac, data_num, reg_addr, pkt);

	// 配置验证失败，程序退出
	if (ret == -1)
	{
		return -1;
	}

	return 0;
}

int cfg_slave_port(u16 hcp_mid, u8 *pkt, u32 reg_data)
{
	int ret = 0;
	u32 data = 0;
	u32 reg_addr = 0;
	u8 i = 0;
	u32 bit_value = 0;

	for (i = 0; i < 32; i++) // 测试仪只支持0，1，2，3口
	{
		bit_value = 0x00000001 << i;
		data = ((reg_data & bit_value) != 0) ? 1 : 0;

		if (i < 8)
		{
			reg_addr = SLAVE_PORT_P0_REG + 0x400000 * i;
		}
		else
		{
			reg_addr = SLAVE_PORT_P8_REG + 0x200000 * (i - 8);
		}

		if (data == 0)
			continue;

		ret = cfg_reg_value(hcp_mid, pkt, htonl(data), htonl(reg_addr));
		if (ret == -1)
		{
			printf("cfg_slave_port_p%d fail \n", i);
			return -1;
		}
	}

	return 0;
}

int cfg_slave_node_sync_para(sync_context sync_para_context, u16 oss_mid, u8 *pkt)
{
	u16 gm_mid = 0;
	int i = 0;
	node_info *temp_node_info = NULL;
	int ret = 0;
	u16 hcp_mid = 0;
	node_cfg_para temp_node_data = {0};

	gm_mid = sync_para_context.context_info.gm_mid;

	for (i = 0; i < MAX_NODE_NUM; i++)
	{
		temp_node_info = sync_para_context.context_info.node_context[i];

		if ((i != gm_mid) && (temp_node_info != NULL))
		{
			hcp_mid = sync_para_context.context_info.node_context[i]->cfg_para.mid;
			temp_node_data = sync_para_context.context_info.node_context[i]->cfg_para;

			printf("Start cfg slave node: mid = %d ! \n", hcp_mid);

			// 1.配置OSS软件的MAC地址
			ret = cfg_reg_value(hcp_mid, pkt, htonl(oss_mid), htonl(CID_REG));
			if (ret == -1)
			{
				printf("1.cfg_oss_mac fail \n");
				return -1;
			}

			// 2.配置同步周期
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.sync_period), htonl(SYNC_PERIOD_REG));
			if (ret == -1)
			{
				printf("2.cfg_sync_period fail \n");
				return -1;
			}

			// 3.配置链路延时测量周期
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.measure_period), htonl(MEASURE_PERIOD_REG));
			if (ret == -1)
			{
				printf("3.cfg_measure_period fail \n");
				return -1;
			}

			// 4.配置链路延时测量超时时间
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.measure_timeout), htonl(MEASURE_RESPONDER_WAIT_TIME_REG));
			if (ret == -1)
			{
				printf("4.cfg_measure_timeout fail \n");
				return -1;
			}

			// 5.配置从时钟与主时钟的同步偏差阈值
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.offset_threshold), htonl(OFFSET_THRESHOLD_REG));
			if (ret == -1)
			{
				printf("5.cfg_offset_threshold fail \n");
				return -1;
			}

			// 6.配置链路延时测量和状态上报使能
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.report_enable), htonl(STATE_REPORT_ENABLED_REG));
			if (ret == -1)
			{
				printf("6.cfg_report_enable fail \n");
				return -1;
			}

			// 7.配置同步主端口
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.master_port), htonl(MASTER_PORT_REG));
			if (ret == -1)
			{
				printf("7.cfg_master_port fail \n");
				return -1;
			}

			// 8.配置同步从端口
			ret = cfg_slave_port(hcp_mid, pkt, temp_node_data.slave_port);
			if (ret == -1)
			{
				printf("8.cfg_slave_port fail \n");
				return -1;
			}

			// 9.配置GM节点标志
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.gm_flag), htonl(GM_ROLE_REG));
			if (ret == -1)
			{
				printf("9.cfg_gm_flag fail \n");
				return -1;
			}

			// 10.配置端口ptp使能
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.port_ptp_enabled), htonl(PORT_PTP_ENABLED_REG));
			if (ret == -1)
			{
				printf("10.cfg_port_ptp_enabled fail \n");
				return -1;
			}

			// 11.配置同步模式
			// ret = cfg_reg_value(hcp_mid, pkt, htonl(step_mode), htonl(STEP_MODE));
			if (ret == -1)
			{
				printf("11.cfg_step_mode fail \n");
				return -1;
			}
		}
	}

	return 0;
}

int cfg_gm_node_sync_para(sync_context sync_para_context, u16 oss_mid, u8 *pkt)
{
	u16 gm_mid = 0;
	int i = 0;
	int ret = 0;
	u16 hcp_mid = 0;
	node_cfg_para temp_node_data = {0};

	gm_mid = sync_para_context.context_info.gm_mid;

	for (i = 0; i < MAX_NODE_NUM; i++)
	{
		if (i == gm_mid)
		{
			hcp_mid = sync_para_context.context_info.node_context[i]->cfg_para.mid;
			temp_node_data = sync_para_context.context_info.node_context[i]->cfg_para;

			printf("Start cfg gm node: mid = %d ! \n", hcp_mid);

			// 1.配置OSS软件的MAC地址
			ret = cfg_reg_value(hcp_mid, pkt, htonl(oss_mid), htonl(CID_REG));
			if (ret == -1)
			{
				printf("1.cfg_oss_mac fail \n");
				return -1;
			}

			// 2.配置同步周期
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.sync_period), htonl(SYNC_PERIOD_REG));
			if (ret == -1)
			{
				printf("2.cfg_sync_period fail \n");
				return -1;
			}

			// 3.配置链路延时测量周期
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.measure_period), htonl(MEASURE_PERIOD_REG));
			if (ret == -1)
			{
				printf("3.cfg_measure_period fail \n");
				return -1;
			}

			// 4.配置链路延时测量超时时间
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.measure_timeout), htonl(MEASURE_RESPONDER_WAIT_TIME_REG));
			if (ret == -1)
			{
				printf("4.cfg_measure_timeout fail \n");
				return -1;
			}

			// 5.配置从时钟与主时钟的同步偏差阈值
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.offset_threshold), htonl(OFFSET_THRESHOLD_REG));
			if (ret == -1)
			{
				printf("5.cfg_offset_threshold fail \n");
				return -1;
			}

			// 6.配置链路延时测量和状态上报使能
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.report_enable), htonl(STATE_REPORT_ENABLED_REG));
			if (ret == -1)
			{
				printf("6.cfg_report_enable fail \n");
				return -1;
			}

			// 7.配置同步主端口
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.master_port), htonl(MASTER_PORT_REG));
			if (ret == -1)
			{
				printf("7.cfg_master_port fail \n");
				return -1;
			}

			// 8.配置同步从端口
			ret = cfg_slave_port(hcp_mid, pkt, temp_node_data.slave_port);
			if (ret == -1)
			{
				printf("8.cfg_slave_port fail \n");
				return -1;
			}

			// 9.配置端口ptp使能
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.port_ptp_enabled), htonl(PORT_PTP_ENABLED_REG));
			if (ret == -1)
			{
				printf("9.cfg_port_ptp_enabled fail \n");
				return -1;
			}

			// 10.配置同步模式
			// ret = cfg_reg_value(hcp_mid, pkt, htonl(step_mode), htonl(STEP_MODE));
			if (ret == -1)
			{
				printf("10.cfg_step_mode fail \n");
				return -1;
			}

			// 11.配置GM节点标志
			ret = cfg_reg_value(hcp_mid, pkt, htonl(temp_node_data.gm_flag), htonl(GM_ROLE_REG));
			if (ret == -1)
			{
				printf("11.cfg_gm_flag fail \n");
				return -1;
			}

			break;
		}
	}

	return 0;
}

int sync_para_cfg(u8 *network_interface, sync_context *sync_para_context, u8 *sync_para_cfg_file_name)
{
	u16 oss_mid = 0;
	int ret = 0;
	// 申请空间，用于构造配置报文
	u8 *pkt = NULL;

	ret = get_sync_cfg_info(sync_para_cfg_file_name, sync_para_context, &oss_mid);
	if (ret == -1)
	{
		printf("get_sync_cfg_info fail \n");
		return -1;
	}

	set_controller_mac(oss_mid, OPENSYNC_APP);

	pkt = (u8 *)malloc(MAX_PKT_LEN);
	if (NULL == pkt)
	{
		printf("sync_para_cfg, malloc buf fail\n");
		return -1;
	}

	bzero(pkt, MAX_PKT_LEN);

	// 配置从时钟节点的同步参数
	ret = cfg_slave_node_sync_para(*sync_para_context, oss_mid, pkt);
	if (ret == -1)
	{
		printf("cfg_slave_node_sync_para fail \n");
		free(pkt);
		return -1;
	}

	// 配置主时钟节点的同步参数
	ret = cfg_gm_node_sync_para(*sync_para_context, oss_mid, pkt);
	if (ret == -1)
	{
		printf("cfg_gm_node_sync_para fail \n");
		free(pkt);
		return -1;
	}

	// 释放申请的空间
	free(pkt);

	return 0;
}

int strtime_to_valuetime(u8 *strtime, u32 *time_ns, u64 *time_s)
{
	u32 tmp_time_ns = 0;
	u64 tmp_time_s = 0;

	memcpy((u8 *)&tmp_time_s, (u8 *)&strtime[0], 6);
	memcpy((u8 *)&tmp_time_ns, (u8 *)&strtime[6], 4);

	*time_s = ntohll(tmp_time_s);
	*time_ns = ntohl(tmp_time_ns);

	*time_s = *time_s >> 16;

	return 0;
}

int recvtime_to_valuetime(u8 *strtime, u32 *recvtime_integer, u16 *recvtime_decimal)
{
	u16 tmp_recvtime_decimal = 0;
	u32 tmp_recvtime_integer = 0;

	memcpy((u8 *)&tmp_recvtime_integer, (u8 *)&strtime[4], 4);
	memcpy((u8 *)&tmp_recvtime_decimal, (u8 *)&strtime[8], 2);

	*recvtime_integer = ntohl(tmp_recvtime_integer);
	*recvtime_decimal = ntohs(tmp_recvtime_decimal);

	//*recvtime_integer = *recvtime_integer >> 8;

	return 0;
}

int ticklen_to_valuetime(u8 *strtime, u8 *tick_integer, u64 *tick_decimal)
{
	u8 tmp_tick_integer1 = 0;
	u8 tmp_tick_integer2 = 0;
	u64 tmp_tick_decimal = 0;
	u8 tmp_str[8] = {0};

	memcpy(tmp_str, strtime, 8);

	tmp_tick_integer1 = strtime[1] & 0x1;
	if (tmp_tick_integer1)
	{
		tmp_tick_integer1 = 128;
	}

	tmp_tick_integer2 = strtime[2] >> 1;

	*tick_integer = tmp_tick_integer1 + tmp_tick_integer2;

	tmp_str[0] = 0x0;
	tmp_str[1] = 0x0;
	tmp_str[2] = tmp_str[2] & 0x1;

	memcpy((u8 *)&tmp_tick_decimal, tmp_str, 8);

	*tick_decimal = ntohll(tmp_tick_decimal);

	return 0;
}

int corrtime_to_valuetime(u8 *strtime, u64 *corrtime_integer, u16 *corrtime_decimal)
{
	u16 tmp_corrtime_decimal = 0;
	u64 tmp_corrtime_integer = 0;

	memcpy((u8 *)&tmp_corrtime_integer, (u8 *)&strtime[0], 6);
	memcpy((u8 *)&tmp_corrtime_decimal, (u8 *)&strtime[6], 2);

	*corrtime_integer = ntohll(tmp_corrtime_integer);
	*corrtime_decimal = ntohs(tmp_corrtime_decimal);

	*corrtime_integer = *corrtime_integer >> 16;

	return 0;
}

u64 sub_time_compute(u8 *time1, u8 *time2)
{
	u32 sub_time_ns = 0;
	u32 time1_ns = 0;
	u32 time2_ns = 0;
	u64 sub_time_s = 0;
	u64 time1_s = 0;
	u64 time2_s = 0;
	u64 sub_value = 0;

	memcpy((u8 *)&time1_s, (u8 *)&time1[0], 6);
	memcpy((u8 *)&time2_s, (u8 *)&time2[0], 6);
	memcpy((u8 *)&time1_ns, (u8 *)&time1[6], 4);
	memcpy((u8 *)&time2_ns, (u8 *)&time2[6], 4);

	time1_s = ntohll(time1_s);
	time2_s = ntohll(time2_s);
	time1_ns = ntohl(time1_ns);
	time2_ns = ntohl(time2_ns);

	// t1或t2值为0，错误
	if (((time1_s || time1_ns) == 0) || ((time2_s || time2_ns) == 0))
	{
		write_debug_msg("delay error! time1 or time2 is 0. \n");
		return 0;
	}

	// t1小于等于t2值，错误
	if ((time1_s < time2_s) || ((time1_s == time2_s) && (time1_ns <= time2_ns)))
	{
		write_debug_msg("delay error! time1 <= time2.\n");
		return 0;
	}

	sub_time_s = (time1_s >> 16) - (time2_s >> 16);
	if (time1_ns > time2_ns)
	{
		sub_time_ns = time1_ns - time2_ns;
	}
	else
	{
		sub_time_ns = (1000000000 + time1_ns) - time2_ns;
		sub_time_s = sub_time_s - 1; // 借1位
	}
	sub_value = sub_time_s * 1000000000 + sub_time_ns;

	return sub_value;
}

int t1_t2_t3_t4_write_file(u32 port, u8 *time1, u8 *time2, u8 *time3, u8 *time4)
{
	u32 t1_ns = 0;
	u64 t1_s = 0;

	u32 t2_ns = 0;
	u64 t2_s = 0;

	u32 t3_ns = 0;
	u64 t3_s = 0;

	u32 t4_ns = 0;
	u64 t4_s = 0;

	strtime_to_valuetime(time1, &t1_ns, &t1_s);
	strtime_to_valuetime(time2, &t2_ns, &t2_s);
	strtime_to_valuetime(time3, &t3_ns, &t3_s);
	strtime_to_valuetime(time4, &t4_ns, &t4_s);

	DELAY_LOG("portid = %u,t1 = %llu sec %u ns, t2 = %llu sec %u ns,t3 = %llu sec %u ns,t4 = %llu sec %u ns \n",
						port, t1_s, t1_ns, t2_s, t2_ns, t3_s, t3_ns, t4_s, t4_ns);

	return 0;
}

void read_reg_value(u8 *local_mac, u16 data_num, u32 addr, u8 *pkt)
{
	u32 *read_data = NULL; // 读回来的数据

	// 清空pkt
	bzero(pkt, MAX_PKT_LEN);

	// read_data内容直接放到pkt中，省去再次赋值
	read_data = (u32 *)(pkt + sizeof(tsmp_header) + sizeof(tsmp_set_req_or_get_res_pkt_data));

	tsmp_get_req(local_mac, data_num, addr, pkt); // 读请求

	return;
}

void get_res_pkt_process(sync_context *sync_para_context, u8 *pkt, sync_state_table *state_table)
{
	u8 local_mac[6] = {0};
	u16 hcp_mid = 0;
	tsmp_set_req_or_get_res_pkt_data *tmp_data = NULL;
	tsmp_header *tmp_header = NULL;
	u32 *read_data = NULL;
	u8 port_id = 0;

	node_info *temp_node_info = NULL;
	node_check_info *temp_check_info = NULL;
	u32 offset = 0;
	u32 bit_flag = 0;
	int ret = 0;

	tmp_header = (tsmp_header *)pkt;
	tmp_data = (tsmp_set_req_or_get_res_pkt_data *)(pkt + sizeof(tsmp_header));

	// 取出源mac及hcp_mid
	memcpy(local_mac, (u8 *)&tmp_header->smac, 6);
	hcp_mid = get_mid_from_mac(local_mac);

	// 定义指针，便于给sync_para_context赋值
	temp_node_info = sync_para_context->context_info.node_context[hcp_mid];
	temp_check_info = &temp_node_info->check_info;

	if ((ntohl(tmp_data->base_addr) == CUMULATIVE_SCALED_RATE_OFFSET) || (ntohl(tmp_data->base_addr) == FCOR_H_CFG) || (ntohl(tmp_data->base_addr) == FCOR_L_CFG))
	{
		if (ntohl(tmp_data->base_addr) == CUMULATIVE_SCALED_RATE_OFFSET)
		{
			offset = CUMULATIVE_SCALED_RATE_REG_OFFSET;
			bit_flag = CUMULATIVE_SCALED_RATE_REG_BIT;
		}
		else if (ntohl(tmp_data->base_addr) == FCOR_H_CFG)
		{
			offset = FCOR_H_REG_OFFSET;
			bit_flag = FCOR_H_REG_BIT;
		}

		ret = memcmp(((u8 *)&temp_check_info->buf) + offset, pkt + sizeof(tsmp_header), 10);
		if (ret == 0) // 校验成功
		{
			// 将寄存器对应的bit位置0
			temp_check_info->check_flag &= ~(0x00000001 << bit_flag);
		}
	}

	if ((ntohl(tmp_data->base_addr) >= MEASURE_REQ_COUNT_BASE_REG) && (ntohl(tmp_data->base_addr) <= (MEASURE_REQ_COUNT_BASE_REG + 0x3F)))
	{
		read_data = (u32 *)(pkt + sizeof(tsmp_header) + sizeof(tsmp_set_req_or_get_res_pkt_data));
		port_id = (ntohl(tmp_data->base_addr) - MEASURE_REQ_COUNT_BASE_REG) >> 1;

		// printf("measure_req_and_resp_reg value of node %d, port %d is 0x%08x, 0x%08x! \n",
		// 	   hcp_mid, port_id, ntohl(read_data[0]), ntohl(read_data[1]));
		write_debug_msg("measure_req_and_resp_reg value of node %d, port %d is 0x%08x, 0x%08x! \n",
										hcp_mid, port_id, ntohl(read_data[0]), ntohl(read_data[1]));
	}

#if 1
	if ((ntohl(tmp_data->base_addr) == SYNC_STATE))
		sync_state_pkt_process(sync_para_context, pkt, state_table, fre_switch);
	else if ((ntohl(tmp_data->base_addr) == DELAY_STATE))
		delay_state_pkt_process(sync_para_context, pkt, fre_switch);
#endif

	return;
}

// 获取当前时刻（ns）
u64 get_cur_nano_sec()
{
	unsigned long CurNanoSec;
	struct timespec tv;
	clock_gettime(ITIMER_REAL, &tv);
	CurNanoSec = tv.tv_sec * 1000000000 + tv.tv_nsec;

	return CurNanoSec;
}

/**
 * 计算两个时间的差值
 * @param cur_time 当前时刻，64bit 以纳秒为单位
 * @param start_time 起始时刻，64bit 以纳秒为单位
 * @return 两个时刻之间的差值
 */
u64 get_diff(u64 cur_time, u64 start_time)
{
	u64 diff = cur_time - start_time;
	return diff;
}

// 软件主动读取
void state_read(sync_context *sync_para_context)
{
	u16 gm_mid = sync_para_context->context_info.gm_mid;
	u16 hcp_mid = 0;
	node_info *temp_node_info = NULL;
	u64 cur_time_count_ns = get_cur_nano_sec(); // 获取当前系统时间
	u8 *pkt = NULL;
	u8 local_mac[6] = {0};
	u16 data_num = 0;

	pkt = (u8 *)malloc(MAX_PKT_LEN);
	if (NULL == pkt)
	{
		printf("sync_para_cfg, malloc buf fail\n");
		return;
	}
	bzero(pkt, MAX_PKT_LEN);

	if (get_diff(cur_time_count_ns, g_timer_array[0]) >=
			(u64)(1 << sync_para_context->context_info.node_context[gm_mid]->cfg_para.sync_period) * 1000000)
	{
		for (int i = 0; i < MAX_NODE_NUM; i++)
		{
			data_num = 24;
			temp_node_info = sync_para_context->context_info.node_context[i];
			if ((i != gm_mid) && (temp_node_info != NULL))
			{
				hcp_mid = sync_para_context->context_info.node_context[i]->cfg_para.mid;
				get_hcp_mac_from_mid(local_mac, hcp_mid);
				tsmp_get_req(local_mac, data_num, htonl(SYNC_STATE), pkt); // 读请求
				g_timer_array[0] = cur_time_count_ns;
			}
		}
	}

	if (get_diff(cur_time_count_ns, g_timer_array[1]) >=
			(u64)(1 << sync_para_context->context_info.node_context[gm_mid]->cfg_para.measure_period) * 1000000)
	{
		data_num = 96;
		for (int i = 0; i < MAX_NODE_NUM; i++)
		{
			temp_node_info = sync_para_context->context_info.node_context[i];
			if (temp_node_info != NULL)
			{
				hcp_mid = sync_para_context->context_info.node_context[i]->cfg_para.mid;
				get_hcp_mac_from_mid(local_mac, hcp_mid);

				tsmp_get_req(local_mac, data_num, htonl(DELAY_STATE), pkt); // 读请求
				g_timer_array[1] = cur_time_count_ns;
			}
		}
	}

	free(pkt);
	return;
}

// test 0620 delay && offset
int sync_state_supervisor(sync_context *sync_para_context, opensync_reg_data *run_data, sync_state_table *state_table)
{
	u16 pkt_len = 1; // 报文长度
	u8 *pkt = NULL;	 // 报文的指针

	// printf("protocol_type=%d,master_mid=%d,sync_period=%d\n",ntohl(run_data->protocol_type),ntohl(run_data->master_mid),ntohl(run_data->sync_period));
	u16 process_type = 1;

#ifdef READ
	process_type = 1;
	write_debug_msg("READ_TYPE \n");
#endif

#ifdef REPORT
	process_type = 0;
	write_debug_msg("REPORT_TYPE \n");
#endif

	if (!process_type)
		while (1)
		{
			// 阻塞接收报文
			pkt = tsmp_pkt_receive_dispatch_1(&pkt_len);

#if 0
		pkt = (u8 *)malloc(MAX_PKT_LEN);
		
		generate_debug_pkt(pkt, &pkt_len); //调试用的
		printf("1.下面是北向应用报文!!!!!!!!!\n");
		cnc_pkt_print(pkt,pkt_len);

		// 释放申请的空间
		if(pkt != NULL)
		{
			free(pkt);
		}
#endif

			if (pkt == NULL)
			{
				continue;
			}
			else if (pkt[12] == 0xff && pkt[13] == 0x01 && pkt[14] == 0x06 && pkt[15] == 0x05) // 判断是否为时间同步状态上报报文
			{
				sync_state_pkt_process(sync_para_context, pkt, state_table, fre_switch);
			}
			else if (pkt[12] == 0xff && pkt[13] == 0x01 && pkt[14] == 0x06 && pkt[15] == 0x06) // 判断是否为链路状态上报报文
			{
				delay_state_pkt_process(sync_para_context, pkt, fre_switch);
			}
			else if (pkt[12] == 0xff && pkt[13] == 0x01 && pkt[14] == 0x02 && pkt[15] == 0x03) // 判断是否为读响应报文
			{
				get_res_pkt_process(sync_para_context, pkt, state_table);
			}
			else // TSNInsight报文处理
			{
				remote_pkt_process(pkt, pkt_len, run_data, state_table);
				// return -1;
			}
		}
	else
	{
		while (1)
		{
			state_read(sync_para_context);
			// 阻塞接收报文
			pkt = tsmp_pkt_receive_dispatch_1(&pkt_len);

			if (pkt == NULL)
			{
				continue;
			}

			if (pkt[12] == 0xff && pkt[13] == 0x01 && pkt[14] == 0x02 && pkt[15] == 0x03) // 判断是否为读响应报文
			{
				get_res_pkt_process(sync_para_context, pkt, state_table);
			}
			else // TSNInsight报文处理
			{
				remote_pkt_process(pkt, pkt_len, run_data, state_table);
				// return -1;
			}
		}
	}

	return -1;
}

void sync_context_destory(sync_context *sync_contex_data)
{
	node_info *temp_node_info = NULL;
	port_delay_state *temp_port_delay_state = NULL;
	int i = 0, j = 0;

	for (i = 0; i < MAX_NODE_NUM; i++)
	{
		temp_node_info = sync_contex_data->context_info.node_context[i];

		if (temp_node_info != NULL)
		{
			for (j = 0; j < MAX_PORT_NUM; j++)
			{
				temp_port_delay_state = temp_node_info->delay_state.port_delay_info[j];

				if (temp_port_delay_state != NULL)
				{
					free(temp_port_delay_state);
				}
			}

			free(temp_node_info);
		}
	}

	return;
}
